#!/usr/bin/env python3
"""
macOS平台打包模块
提供macOS平台专用的应用程序打包功能
"""

import os
import subprocess
import shutil
from pathlib import Path
import tomli

# 项目根目录
PROJECT_ROOT = Path(__file__).parent.parent
RESOURCES_DIR = PROJECT_ROOT / "resources"
BUILD_DIR = PROJECT_ROOT / "build"
DIST_DIR = PROJECT_ROOT / "dist"

def build_macos_package(name, main_script, config):
    """
    macOS平台打包
    
    参数:
        name (str): 应用程序名称
        main_script (str): 主脚本文件名
        config (object): 打包配置对象，包含以下属性：
            - one_file (bool): 是否使用单文件模式
            - windowed (bool): 是否使用窗口模式
            - build_type (str): 打包类型 ('app' 或 'installer')
    
    返回:
        bool: 打包是否成功
    """
    print("正在打包macOS应用程序...")
    
    cmd = [
        "pyinstaller",
        "--name", name,
        "--distpath", str(DIST_DIR),
        "--workpath", str(BUILD_DIR),
        "--specpath", str(BUILD_DIR),
    ]
    
    if config.one_file:
        cmd.append("--onefile")
    
    if config.windowed:
        cmd.append("--windowed")
    
    # 添加图标
    icon_path = RESOURCES_DIR / "icons" / "app-icon.icns"
    if icon_path.exists():
        cmd.extend(["--icon", str(icon_path)])
    
    # 添加数据文件
    cmd.extend(["--add-data", f"{RESOURCES_DIR}{os.pathsep}resources"])
    
    # PySide6相关配置
    cmd.extend([
        "--hidden-import", "PySide6.QtCore",
        "--hidden-import", "PySide6.QtGui", 
        "--hidden-import", "PySide6.QtWidgets",
        "--collect-all", "PySide6",
        "--collect-all", "shiboken6"
    ])
    
    cmd.append(str(PROJECT_ROOT / main_script))
    
    try:
        subprocess.run(cmd, check=True)
        print("macOS应用程序打包完成!")
        
        if config.build_type == "installer":
            return _create_macos_installer(name)
        
        print(f"输出目录: {DIST_DIR}")
        return True
        
    except subprocess.CalledProcessError as e:
        print(f"打包失败: {e}")
        return False

def _create_macos_installer(name):
    """创建macOS安装程序（DMG格式）"""
    print("创建macOS DMG安装程序...")
    
    # 检查是否在macOS系统上
    if os.name != 'posix' or subprocess.run(['uname'], capture_output=True).stdout.decode().strip() != 'Darwin':
        print("警告: 只能在macOS系统上创建DMG安装程序")
        return True
    
    # 检查必要工具
    try:
        subprocess.run(["hdiutil", "-help"], check=True, capture_output=True)
    except (subprocess.CalledProcessError, FileNotFoundError):
        print("警告: hdiutil工具不可用，跳过DMG创建")
        return True
    
    try:
        app_path = DIST_DIR / f"{name}.app"
        if not app_path.exists():
            # 如果是单文件模式，先创建.app包
            app_path = _create_macos_app_bundle(name)
        
        if not app_path.exists():
            print("无法找到应用程序包")
            return False
        
        # 创建DMG镜像
        dmg_path = DIST_DIR / f"{name}.dmg"
        temp_dmg = BUILD_DIR / f"{name}_temp.dmg"
        
        # 计算DMG大小
        app_size = sum(f.stat().st_size for f in app_path.rglob('*') if f.is_file())
        dmg_size = max(app_size * 2, 50 * 1024 * 1024)  # 至少50MB
        
        # 创建临时DMG
        subprocess.run([
            "hdiutil", "create", "-size", f"{dmg_size // (1024*1024)}m",
            "-fs", "HFS+", "-volname", name,
            str(temp_dmg)
        ], check=True)
        
        # 挂载DMG
        result = subprocess.run(["hdiutil", "attach", str(temp_dmg)], 
                            capture_output=True, text=True, check=True)
        mount_point = None
        for line in result.stdout.splitlines():
            if name in line:
                mount_point = line.split('\t')[-1]
                break
        
        if not mount_point:
            print("无法挂载DMG")
            return False
        
        # 复制应用到DMG
        shutil.copytree(app_path, Path(mount_point) / f"{name}.app")
        
        # 创建符号链接到Applications
        applications_link = Path(mount_point) / "Applications"
        if not applications_link.exists():
            applications_link.symlink_to("/Applications")
        
        # 卸载DMG
        subprocess.run(["hdiutil", "detach", mount_point], check=True)
        
        # 压缩DMG
        subprocess.run([
            "hdiutil", "convert", str(temp_dmg), "-format", "UDZO",
            "-o", str(dmg_path), "-imagekey", "zlib-level=9"
        ], check=True)
        
        # 清理临时文件
        temp_dmg.unlink(missing_ok=True)
        
        if dmg_path.exists():
            print(f"macOS DMG安装程序创建完成: {dmg_path}")
            return True
        else:
            print("DMG创建失败")
            return False
            
    except Exception as e:
        print(f"创建DMG安装程序失败: {e}")
        return False

def _create_macos_app_bundle(name):
    """创建macOS .app应用包"""
    app_path = DIST_DIR / f"{name}.app"
    contents_dir = app_path / "Contents"
    macos_dir = contents_dir / "MacOS"
    resources_dir = contents_dir / "Resources"
    
    # 创建目录结构
    macos_dir.mkdir(parents=True, exist_ok=True)
    resources_dir.mkdir(parents=True, exist_ok=True)
    
    # 复制可执行文件
    exe_path = DIST_DIR / name
    if exe_path.exists():
        shutil.copy2(exe_path, macos_dir / name)
        (macos_dir / name).chmod(0o755)
    
    # 从pyproject.toml读取版本信息
    pyproject_path = PROJECT_ROOT / "pyproject.toml"
    with open(pyproject_path, 'rb') as f:
        pyproject_data = tomli.load(f)
    version = pyproject_data.get('project', {}).get('version', '1.0.0')
    
    # 创建Info.plist
    info_plist = f"""<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CFBundleExecutable</key>
    <string>{name}</string>
    <key>CFBundleIdentifier</key>
    <string>com.example.{name}</string>
    <key>CFBundleName</key>
    <string>{name}</string>
    <key>CFBundleVersion</key>
    <string>{version}</string>
    <key>CFBundlePackageType</key>
    <string>APPL</string>
    <key>LSUIElement</key>
    <string>0</string>
</dict>
</plist>"""
    
    with open(contents_dir / "Info.plist", 'w') as f:
        f.write(info_plist)
    
    return app_path